import { saveAs } from 'file-saver'
import { StoryboardData } from '../../../types/document'
import { 
  ExportType, 
  ExportOptions, 
  ExportResult, 
  ExportEngine, 
  ExportProgress 
} from './types'
import { StoryboardDataTransformerFixed } from './StoryboardDataTransformerFixed'
import { PDFExportEngine } from './PDFExportEngine'
import { ExcelExportEngine } from './ExcelExportEngine'
import { TextExportEngine, MarkdownExportEngine } from './TextExportEngine'

/**
 * 分镜导出管理器
 * 统一管理各种格式的导出操作
 */
export class StoryboardExportManager {
  private engines: Map<ExportType, ExportEngine>
  private transformer: StoryboardDataTransformerFixed
  
  constructor() {
    this.transformer = new StoryboardDataTransformerFixed()
    this.engines = new Map([
      [ExportType.PDF, new PDFExportEngine()],
      [ExportType.EXCEL, new ExcelExportEngine()],
      [ExportType.TEXT, new TextExportEngine()],
      [ExportType.MARKDOWN, new MarkdownExportEngine()]
    ])
  }
  
  /**
   * 导出分镜脚本
   */
  async exportStoryboard(
    storyboardData: StoryboardData,
    options: ExportOptions,
    projectTitle?: string,
    onProgress?: (progress: ExportProgress) => void
  ): Promise<ExportResult> {
    try {
      onProgress?.({
        stage: 'preparing',
        progress: 0,
        message: '开始导出分镜脚本...'
      })
      
      // 获取导出引擎
      const engine = this.engines.get(options.type)
      if (!engine) {
        throw new Error(`不支持的导出格式: ${options.type}`)
      }
      
      // 转换数据
      const exportData = this.transformer.transform(storyboardData, projectTitle)
      
      // 生成文件
      const blob = await engine.generate(exportData, options, onProgress)
      
      // 生成文件名
      const fileName = this.generateFileName(projectTitle || '分镜脚本', options)
      
      // 自动下载
      if (options.type !== ExportType.TEXT && options.type !== ExportType.MARKDOWN) {
        saveAs(blob, fileName)
      } else {
        saveAs(blob, fileName)
      }
      
      return {
        success: true,
        blob,
        fileName,
        fileSize: blob.size
      }
      
    } catch (error) {
      const errorMessage = error instanceof Error ? error.message : String(error)
      
      onProgress?.({
        stage: 'error',
        progress: 0,
        message: '导出失败',
        error: errorMessage
      })
      
      return {
        success: false,
        fileName: '',
        error: errorMessage
      }
    }
  }
  
  /**
   * 预览导出内容
   */
  async previewExport(
    storyboardData: StoryboardData,
    options: ExportOptions,
    projectTitle?: string
  ): Promise<string> {
    const engine = this.engines.get(options.type)
    if (!engine || !engine.preview) {
      throw new Error(`${options.type} 格式不支持预览`)
    }
    
    const exportData = this.transformer.transform(storyboardData, projectTitle)
    return engine.preview(exportData, options)
  }
  
  /**
   * 获取支持的导出格式
   */
  getSupportedFormats(): ExportType[] {
    return Array.from(this.engines.keys())
  }
  
  /**
   * 获取格式的支持选项
   */
  getSupportedOptions(type: ExportType): Partial<ExportOptions> {
    const engine = this.engines.get(type)
    return engine?.getSupportedOptions() || {}
  }
  
  /**
   * 批量导出多种格式
   */
  async batchExport(
    storyboardData: StoryboardData,
    formats: ExportType[],
    baseOptions: Omit<ExportOptions, 'type'>,
    projectTitle?: string,
    onProgress?: (format: ExportType, progress: ExportProgress) => void
  ): Promise<ExportResult[]> {
    const results: ExportResult[] = []
    
    for (const format of formats) {
      const options: ExportOptions = { ...baseOptions, type: format }
      
      const result = await this.exportStoryboard(
        storyboardData,
        options,
        projectTitle,
        onProgress ? (progress) => onProgress(format, progress) : undefined
      )
      
      results.push(result)
    }
    
    return results
  }
  
  /**
   * 生成文件名
   */
  private generateFileName(projectTitle: string, options: ExportOptions): string {
    const timestamp = new Date().toISOString().slice(0, 19).replace(/[:-]/g, '')
    const baseName = options.fileName || `${projectTitle}_分镜脚本_${timestamp}`
    
    const extensions: Record<ExportType, string> = {
      [ExportType.PDF]: 'pdf',
      [ExportType.EXCEL]: 'xlsx',
      [ExportType.TEXT]: 'txt',
      [ExportType.MARKDOWN]: 'md'
    }
    
    const extension = extensions[options.type]
    return `${baseName}.${extension}`
  }
  
  /**
   * 验证导出选项
   */
  validateOptions(options: ExportOptions): { valid: boolean; errors: string[] } {
    const errors: string[] = []
    
    // 检查导出类型
    if (!this.engines.has(options.type)) {
      errors.push(`不支持的导出格式: ${options.type}`)
    }
    
    // 检查选中场景
    if (!options.includeAll && (!options.selectedSceneIds || options.selectedSceneIds.length === 0)) {
      errors.push('请选择要导出的场景')
    }
    
    // 检查文件名
    if (options.fileName && !/^[a-zA-Z0-9\u4e00-\u9fa5_\-\s]+$/.test(options.fileName)) {
      errors.push('文件名包含不允许的字符')
    }
    
    return {
      valid: errors.length === 0,
      errors
    }
  }
  
  /**
   * 估算文件大小
   */
  estimateFileSize(
    storyboardData: StoryboardData,
    options: ExportOptions
  ): { size: number; unit: string; description: string } {
    const sceneCount = options.includeAll 
      ? storyboardData.scenes?.length || 0
      : options.selectedSceneIds?.length || 0
    
    // 基于经验值估算
    const baseSizes: Record<ExportType, number> = {
      [ExportType.PDF]: 50, // KB per scene
      [ExportType.EXCEL]: 5, // KB per scene
      [ExportType.TEXT]: 1, // KB per scene
      [ExportType.MARKDOWN]: 1.5 // KB per scene
    }
    
    const baseSize = baseSizes[options.type] || 10
    let estimatedSize = sceneCount * baseSize
    
    // 根据选项调整
    if (options.includeThumbnails) {
      estimatedSize *= 3 // 缩略图会显著增加文件大小
    }
    
    if (options.includeStatistics) {
      estimatedSize += 20 // 统计信息额外大小
    }
    
    // 转换单位
    if (estimatedSize < 1024) {
      return {
        size: Math.round(estimatedSize),
        unit: 'KB',
        description: `约 ${Math.round(estimatedSize)} KB`
      }
    } else {
      const sizeMB = estimatedSize / 1024
      return {
        size: Math.round(sizeMB * 100) / 100,
        unit: 'MB',
        description: `约 ${(Math.round(sizeMB * 100) / 100)} MB`
      }
    }
  }
}